package com.akcome.apollo.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.common.utils.bean.AkResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import com.akcome.apollo.common.AkResultHelper;
import com.akcome.apollo.common.ApolloConstants;
import com.akcome.apollo.common.IpHelper;
import com.akcome.apollo.common.TokenHelper;
import com.akcome.apollo.domain.BmpLoginLog;
import com.akcome.apollo.domain.BmpUser;
import com.akcome.apollo.domain.enums.MsgTemplateEnum;
import com.akcome.apollo.domain.enums.SourceEnum;
import com.akcome.apollo.domain.enums.YesOrNoEnum;
import com.akcome.apollo.domain.resultcode.UserResultCode;
import com.akcome.apollo.repository.BmpUserRepository;
import com.akcome.apollo.service.BmpLoginLogService;
import com.akcome.apollo.service.BmpUserService;
import com.akcome.apollo.service.MailService;


/**
 * 用户信息Service接口实现
 *
 * @author wn
 * @version $v: 1.0.0, $time:2017-12-26 08:49:00 Exp $
 */
@Service
public class BmpUserServiceImpl implements BmpUserService {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private BmpUserRepository bmpUserRepository;
	
	@Autowired
	private TokenHelper tokenHelper;
	
	@Autowired
	private AkResultHelper akResultHelper;
	
	@Value("${loginErrorCount}")
	private int loginErrorCount;
	
	@Autowired
	private MailService mailService;
	
	@Autowired
	private BmpLoginLogService bmpLoginLogService;
	
	@Override
	public BmpUser save(BmpUser bmpUser){
		return bmpUserRepository.save(bmpUser);
	}
	
	@Override
	public BmpUser findOne(Long id){
		return bmpUserRepository.findOne(id);
	}
	
	@Override
	public BmpUser findByEmail(String email){
		return bmpUserRepository.findByEmail(email);
	}
	
	@Override
	public Long countUserError(String email){
		BmpUser bmpUser = findByEmail(email);
		if(null==bmpUser){
			return 0L;
		}
		return bmpUser.getLoginErrorCount();
	}
	
	@Override
	public BmpUser register(String email,String password){
		BmpUser bmpUser = new BmpUser();
		bmpUser.setCreateTime(new Date());
		bmpUser.setEmail(email);
		BCryptPasswordEncoder bc = new BCryptPasswordEncoder(4);
		bmpUser.setPassword(bc.encode(password));
		bmpUser.setSource(SourceEnum.WEB.getCode());
		bmpUser.setEnabled(YesOrNoEnum.YES.getCode());
		bmpUser.setExpired(YesOrNoEnum.NO.getCode());
		bmpUser.setLocked(YesOrNoEnum.NO.getCode());
		bmpUser.setLoginErrorCount(0L);
		Locale locale = LocaleContextHolder.getLocale();
		bmpUser.setLocale(locale.getLanguage()+"_"+locale.getCountry());
		return save(bmpUser);
	}
	
	@Override
	public AkResult login(String email,String password,String imageCode,HttpServletRequest request, HttpServletResponse response) throws Exception{
		//验证用户名面是否正确
		BmpUser bmpUser = findByEmail(email);
		if(null!=bmpUser){
			Long errorCount = bmpUser.getLoginErrorCount();
			if(YesOrNoEnum.NO.getCode().equals(bmpUser.getEnabled())){
				return akResultHelper.buildFailAkResult(UserResultCode.USER_DISABLED);
			}
			
			SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
			if(YesOrNoEnum.YES.getCode().equals(bmpUser.getLocked())&& sf.format(bmpUser.getLockTime()).equals(sf.format(new Date())) ){
				return akResultHelper.buildFailAkResult(UserResultCode.USER_LOCKED);
			}
			
			if(0!=errorCount.intValue()){
				//校验图形码
				if(StringUtils.isBlank(imageCode)){
					return akResultHelper.buildFailAkResult(UserResultCode.IMAGE_CODE_NONE);
				}
				String code = tokenHelper.getTokenText(ApolloConstants.COOKIE_IMAGE_CODE, request);
				if(StringUtils.isBlank(code)){
					return akResultHelper.buildFailAkResult(UserResultCode.IMAGE_CODE_INVALID);
				}
				
				if(!imageCode.toUpperCase().equals(code.toUpperCase())){
					return akResultHelper.buildFailAkResult(UserResultCode.IMAGE_CODE_FAIL);
				}
			}
			BCryptPasswordEncoder bc = new BCryptPasswordEncoder(4);
			if(bc.matches(password, bmpUser.getPassword())){
				//清空错误次数
				bmpUser.setLoginErrorCount(0L);
				save(bmpUser);
				//添加的登录日志
				BmpLoginLog loginLog = new BmpLoginLog();
				loginLog.setCreateTime(new Date());
				loginLog.setIp(IpHelper.getIpAddress(request));
				loginLog.setLoginTime(new Date());
				loginLog.setSource(SourceEnum.WEB.getCode());
				loginLog.setUserId(bmpUser.getId());
				bmpLoginLogService.save(loginLog);
				//生成token
				String token = tokenHelper.generateToken(email);
				Cookie cookie = new Cookie(tokenHelper.getKey(), token);
				cookie.setMaxAge(tokenHelper.getExpiration());
				response.addCookie(cookie);
			}else{
				//密码错误：更新错误次数，达到5次发送邮件，错误一次添加图片验证码
				bmpUser.setLoginErrorCount(errorCount+1L);
				if(errorCount.intValue()+1>=loginErrorCount){
					bmpUser.setLocked(YesOrNoEnum.YES.getCode());
					bmpUser.setLockTime(new Date());
					// 登录错误次数上限，邮件参数组装
					Map<String, Object> model = new HashMap<>();
					model.put("email", email);
					mailService.mailSender(bmpUser.getEmail(), MsgTemplateEnum.MAIL_LOGIN_ERROR, model,LocaleContextHolder.getLocale());
				}
				save(bmpUser);
				return akResultHelper.buildFailAkResult(UserResultCode.PWD_FAIL);
			}
		}else{
			//用户不存在
			return akResultHelper.buildFailAkResult(UserResultCode.USER_NOT_EXIST);
		}
		return akResultHelper.buildSuccessAkResult(null);
	}
	
	
}
